<?php
namespace addons\xiluedu\controller;

use addons\xiluedu\library\Config;
use app\common\model\Readorder;
use app\common\model\xiluedu\CourseOrder;
use app\common\model\xiluedu\OfflineOrder;
use app\common\model\xiluedu\UserCourse;
use app\common\model\xiluedu\VipOrder;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Http\StreamResponse;
use fast\Http;
use think\Controller;
use think\Db;
use think\Exception;
use think\exception\ErrorException;
use think\exception\ThrowableError;
use think\Log;

class WeixinMini extends Controller
{
    protected $app;
    protected $payment;

    public function _initialize()
    {
        parent::_initialize();
        $this->app = Factory::miniProgram(Config::load());
        $wxmini_config = \app\common\model\xiluedu\Config::getMyConfig('wxmini');
        $pay_config = \app\common\model\xiluedu\Config::getMyConfig('wxpayment');
        $payment_config = [
            // 必要配置
            'app_id'             => $wxmini_config['wxmini_appid'] ?? '',
            'mch_id'             => $pay_config['mch_id'] ?? '',
            'key'                => $pay_config['mch_key'] ?? '',   // API 密钥
            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path'          => $pay_config['apiclient_cert'] ?? '', // XXX: 绝对路径！！！！
            'key_path'           => $pay_config['apiclient_key'] ?? '',      // XXX: 绝对路径！！！！
            'notify_url'         => '',     // 你也可以在下单时单独设置来想覆盖它
        ];
        $this->payment = Factory::payment($payment_config);
    }

    /**
     * 登录
     * @param $code
     * @return mixed
     * @throws Exception
     * @throws ThrowableError
     */
    public function wxlogin($code)
    {
        try {
            $result = $this->app->auth->session($code);
            if(isset($result['errcode'])) Throw new Exception($result['errmsg']);
        } catch (Exception $e){
            throw $e;
        }
        return $result;
    }

    /**
     * 手机号解密
     * @param $session_key
     * @param $iv
     * @param $encryptedData
     * @return mixed
     * @throws Exception
     * @throws ThrowableError
     */
    public function wxNumberEncrypted($session_key,$iv,$encryptedData){
        try {
            $result = $this->app->encryptor->decryptData($session_key, $iv, $encryptedData);

        }catch (ThrowableError $e){
            throw $e;
        }catch (Exception $e){
            throw $e;
        }
        return $result;
    }
    /**
     * 信息解密
     * @param $session_key
     * @param $iv
     * @param $encryptedData
     * @return mixed
     * @throws Exception
     * @throws ThrowableError
     */
    public function wxEncrypted($session_key,$iv,$encryptedData){
        try {
            $result = $this->app->encryptor->decryptData($session_key, $iv, $encryptedData);

        }catch (ThrowableError $e){
            throw $e;
        }catch (Exception $e){
            throw $e;
        }
        return $result;
    }

    /**
     * 获取access_token
     */
    public function get_token(){
        $token = $this->app->access_token->getToken();
        return $token;
    }

    /**
     * 获取小程序码-A
     */
    public function getlimited($page)
    {

        $response = $this->app->app_code->get($page);
        $resfilename = '';
        if ($response instanceof StreamResponse) {
            $resfilename = $response->getBodyContents();
        }
        return $resfilename;
    }
    
    /**
     * 获取小程序码-B
     */
    public function getUnlimited($scene,$page)
    {

        $response = $this->app->app_code->getUnlimit($scene,['page'=>$page]);
        $resfilename = '';
        if ($response instanceof StreamResponse) {
            $resfilename = $response->getBodyContents();
        }
        return $resfilename;
    }
    /**
     * 获取access_token
     */
    public function getToken(){
        $token = $this->app->access_token->getToken();
        return $token['access_token'];
    }
    /**
     * 获取手机号
     * @param $code
     */
    public function getPhoneNumber($code){
        $token = $this->getToken();

        try {
            $data = Http::post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=".$token,json_encode(['code'=>$code]));
            $data = json_decode($data,true);
            if($data['errcode'] != '0'){
                throw new Exception("获取手机号失败");
            }
        }catch (ErrorException $exception){

            throw $exception;
        }


        return $data['phone_info'];
    }

    /**
     * 生成统一订单
     */
    public function union_order($order){

        $orderinfo = [
            'body'              => $order['body'],
            'out_trade_no'      => $order['order_no'],
            'total_fee'         => (int)($order['pay_price'] * 100),
            //'spbill_create_ip'  => '123.12.12.123', // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
            'notify_url'        => $order['notify_url'], // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type'        => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid'            => $order['openid'],
        ];
        try {
            $wxpay = $this->payment->order->unify($orderinfo);
            Log::info("微信统一下单接口:" . json_encode($wxpay));
            return $this->payment->jssdk->bridgeConfig($wxpay['prepay_id'], false);
        }catch (Exception $e){
            return [];
        }
    }


    /**
     * 支付回调
     */
    public function notify()
    {
//        Log::record(file_get_contents('php://input'), "notify");
        $table = input('table','course_order');
        $response = $this->payment->handlePaidNotify(function ($message, $fail) use($table){
            // 你的逻辑
            Log::record($message, "debug");
            $order_no = $message['out_trade_no'];
            Db::startTrans();
            switch($table){
                case 'course_order':
                    try {
                        CourseOrder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
                case 'vip_order':
                    try {
                        VipOrder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
                case 'offline_order':
                    try {
                        OfflineOrder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
                case 'read_order':
                    try {
                        Readorder::pay_notify($order_no);
                    }catch (Exception $e){
                        Db::rollback();;
                        return $e->getMessage();
                    }
                    break;
            }
            Db::commit();
            return true;

        });

        $response->send();
        return;
    }

}